#include "icsearch.hpp"
#include <elasticlient/client.h>
#include <cpr/cpr.h>
#include "user.hxx"
#include "message.hxx"
#include <iostream>

namespace xchat
{
class ESClientFactory
{
public:
    static std::shared_ptr<elasticlient::Client> createClient(const std::vector<std::string>& host_list)
    {
        return std::make_shared<elasticlient::Client>(host_list);
    }
};
class ESUser
{
public:
    using ptr = std::shared_ptr<ESUser>;
    ESUser() = delete;
    ESUser(std::shared_ptr<elasticlient::Client> client)
        : _es_client(client)
    {}
    bool createIndex()
    {
        bool ret = ESIndex(_es_client, "user")
                .append("user_id", "keyword", "standard", true)
                .append("nickname", "text", "ik_max_word", true)
                .append("phone", "keyword", "standard", true)
                .append("description", "text", "standard", false)
                .append("avatar_id", "keyword", "standard", false) //keyword，用于关联头像资源（如通过 ID 查询对应的图片 URL），需精确匹配，无需分词。
                .create();
        if (!ret)
        {
            LOG_INFO("用户信息索引创建失败");
            return false;
        }
        LOG_INFO("用户信息索引创建成功");
        return true;
    }
    bool appendData(const std::string& uid, const std::string& phone, const std::string& nickname, 
            const std::string& description, const std::string& avatar_id)
    {
        bool ret = ESInsert(_es_client, "user")
                    .append("user_id", uid)
                    .append("nickname", nickname)
                    .append("phone", phone)
                    .append("description", description)
                    .append("avatar_id", avatar_id)
                    .insert(uid);
        if(ret == false)
        {
            LOG_INFO("数据插入/更新失败");
            return false;
        }
        LOG_INFO("数据插入/更新成功");
        return true;
    }
                    //关键词 uid查询结果 
    std::vector<User> search(const std::string& key, const std::vector<std::string> &uid_list)
    {
        Json::Value user = ESSearch(_es_client, "user")
                        .append_should_match("user_id.keyword", key) //user_id查询时不希望分词
                        .append_should_match("phone.keyword", key) //phone查询时不希望分词
                        .append_should_match("nickname", key) //nickname查询时希望分词
                        .append_must_not_terms("user_id.keyword", uid_list) //排除掉uid_list中的用户
                        .search();
        if(user.empty() || user.isArray() == false)
        {
            LOG_INFO("结果为空 或结果不为数组");
            return std::vector<User>();
        }
        LOG_INFO("数据检索成功！检索结果条目数量：{}" , user.size());
        std::vector<User> user_list;
        for (int i = 0; i < user.size(); i++)
        {
            User userInfo;
            userInfo.user_id(std::string(user[i]["_source"]["user_id"].asString()));

            userInfo.phone(std::string(user[i]["_source"]["phone"].asString()));

            userInfo.nickname(user[i]["_source"]["nickname"].asString());

            userInfo.description(user[i]["_source"]["description"].asString());

            userInfo.avatar_id(user[i]["_source"]["avatar_id"].asString());
            user_list.push_back(userInfo);
        }
        return user_list;
    }
private:
    std::shared_ptr<elasticlient::Client> _es_client;
};
class ESMessage
{
public:
    using ptr = std::shared_ptr<ESMessage>;
    ESMessage(const std::shared_ptr<elasticlient::Client> &es_client)
        : _es_client(es_client)
    {}
    bool createIndex()
    {
        bool ret = ESIndex(_es_client, "message")
                .append("user_id", "keyword", "standard", false)
                .append("message_id", "keyword", "standard", false)
                .append("create_time", "long", "standard", false)  //true 作为索引 用作搜索 false 不作为索引只供存储
                .append("chat_session_id", "keyword", "standard", true)
                .append("content", "text", "ik_max_word", true) //keyword，用于关联头像资源（如通过 ID 查询对应的图片 URL），需精确匹配，无需分词。
                .create();
        if (!ret)
        {
            LOG_INFO("消息信息索引创建失败");
            return false;
        }
        LOG_INFO("消息信息索引创建成功");
        return true;
    }
    bool appendData(const std::string& uid, const std::string& message_id, const long create_time, 
            const std::string& chat_session_id, const std::string& content)  //content类型 TODO
    {
        bool ret = ESInsert(_es_client, "message")
                    .append("user_id", uid)
                    .append("message_id", message_id)
                    .append("create_time", create_time)
                    .append("chat_session_id", chat_session_id)
                    .append("content", content)
                    .insert(message_id); 
        if(ret == false)
        {
            LOG_INFO("消息数据数据插入/更新失败");
            return false;
        }
        LOG_INFO("消息数据数据插入/更新成功");
        return true;
    }
    bool remove(std::string &mid)
    {
        //mid虽然没建立索引 但是根据mid生成es自带的id 跟我们设置的字段没关系
        bool ret = ESRemove(_es_client, "message")
                    .remove(mid);
        if(ret == false)
        {
            LOG_INFO("消息数据删除失败");
            return false;
        }
        LOG_INFO("消息数据删除成功");
        return true;
    }
    std::vector<Message> search(const std::string& content, const std::string &ssid)
    {
        Json::Value messages = ESSearch(_es_client, "message")
                        .append_must_term("chat_session_id.keyword", ssid) 
                        .append_must_match("content", content) 
                        .search();
        if(messages.empty() || messages.isArray() == false)
        {
            LOG_INFO("消息数据结果为空 或结果不为数组");
            return std::vector<Message>();
        }
        LOG_INFO("数据检索成功！检索结果条目数量：{}" , messages.size());
        std::vector<Message> message_list;
        for (int i = 0; i < messages.size(); i++)
        {
            Message message;
            message.user_id(std::string(messages[i]["_source"]["user_id"].asString()));

            message.message_id(std::string(messages[i]["_source"]["message_id"].asString()));

            message.create_time(boost::posix_time::from_time_t(messages[i]["_source"]["create_time"].asInt64()));
            
            message.session_id(messages[i]["_source"]["chat_session_id"].asString());
            
            message.content(messages[i]["_source"]["content"].asString());

            message_list.push_back(message);
        }
        return message_list;
    }
private:
    std::shared_ptr<elasticlient::Client> _es_client;
};

}